package org.finesys.system.controller;


import java.util.List;

import org.finesys.common.constants.CacheConstants;
import org.finesys.common.core.constants.RestApiConfig;
import org.finesys.common.core.module.DeptDataPermissionEntity;
import org.finesys.common.core.module.R;
import org.finesys.common.excel.annotaion.RequestExcel;
import org.finesys.common.excel.annotaion.ResponseExcel;
import org.finesys.common.log.core.annotation.LogAnnotation;
import org.finesys.common.log.core.enums.OperateType;
import org.finesys.common.security.core.module.AuthUser;
import org.finesys.common.security.core.util.SecurityUtils;
import org.finesys.system.api.entity.SysRole;
import org.finesys.system.api.vo.RoleExcelVO;
import org.finesys.system.api.vo.RoleVO;
import org.finesys.system.constants.ControllerRestApiConfig;
import org.finesys.system.service.SysRoleMenuService;
import org.finesys.system.service.SysRoleService;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.http.HttpHeaders;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;


@RestController
@RequiredArgsConstructor
@RequestMapping(ControllerRestApiConfig.ROLE)
@Tag(name = "角色管理模块")
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class SysRoleController {

    private final SysRoleService sysRoleService;

    private final SysRoleMenuService sysRoleMenuService;

    /**
     * 新增角色信息表
     *
     * @param sysRole 角色信息表
     * @return R
     */
    @Operation(summary = "新增角色信息", description = "新增角色信息表")
    @LogAnnotation(title = "新增角色信息", operateType = OperateType.INSERT)
    @PostMapping(RestApiConfig.ADD)
    @PreAuthorize("@pms.hasPermission('sys_role_add')")
    public R<?> save(@RequestBody SysRole sysRole) {
        return R.success(sysRoleService.save(sysRole));
    }

    /**
     * 修改角色信息表
     *
     * @param sysRole 角色信息表
     * @return R
     */
    @Operation(summary = "修改角色信息表", description = "修改角色信息表")
    @LogAnnotation(title = "修改角色信息表", operateType = OperateType.UPDATE)
    @PutMapping(value = RestApiConfig.UPDATE)
    @PreAuthorize("@pms.hasPermission('sys_role_edit')")
    @CacheEvict(value = CacheConstants.ROLE_DETAILS, key = "#sysRole.roleId")
    public R<?> updateById(@RequestBody SysRole sysRole) {
        return R.success(sysRoleService.updateById(sysRole));
    }

    /**
     * 通过id删除角色信息表
     *
     * @param roleIds id
     * @return R
     */
    @Operation(summary = "通过id删除角色信息表", description = "通过id删除角色信息表")
    @LogAnnotation(title = "删除角色", operateType = OperateType.DELETE)
    @DeleteMapping(value = RestApiConfig.DELETE)
    @PreAuthorize("@pms.hasPermission('sys_role_del')")
    public R<?> delete(@RequestBody Long[] roleIds) {
        if (roleIds != null) {
            for (Long roleId : roleIds) {
                sysRoleService.removeRoleById(roleId);
            }
            return R.success();
        }
        return R.failed("请选择至少一条数据");
    }

    /**
     * 通过id查询角色信息表
     *
     * @param roleId id
     * @return R
     */
    @Operation(summary = "通过id查询", description = "通过id查询")
    @GetMapping(RestApiConfig.GET + "/{roleId}")
    public R<?> getById(@PathVariable("roleId") Long roleId) {
        return R.success(sysRoleService.getById(roleId));
    }


    /**
     * 获取角色列表
     *
     * @return 角色列表
     */
    @GetMapping(RestApiConfig.ALL)
    public R<List<SysRole>> findAll() {
        return R.success(sysRoleService.findAll());
    }

    /**
     * 获取角色列表
     *
     * @return 角色列表
     */
    @GetMapping(RestApiConfig.LIST)
    public R<List<SysRole>> findList(SysRole sysRole) {
        return R.success(sysRoleService.findList(sysRole));
    }

    /**
     * 分页查询
     *
     * @param page 分页对象
     * @return
     */
    @Operation(summary = "分页查询", description = "分页查询")
    @GetMapping(RestApiConfig.PAGE)
    public R<?> getPage(Page<SysRole> page, SysRole sysRole) {
        return R.success(sysRoleService.findPage(page, sysRole));
    }


    /**
     * 更新角色菜单
     *
     * @param roleVo 角色对象
     * @return success、false
     */
    @LogAnnotation(title = "更新角色菜单", operateType = OperateType.UPDATE)
    @PutMapping("/menu")
    @PreAuthorize("@pms.hasPermission('sys_role_perm')")
    public R<Boolean> saveRoleMenus(@RequestBody RoleVO roleVo) {
        return R.success(sysRoleMenuService.saveRoleMenus(roleVo));
    }

    /**
     * 获取当前用户角色下的数据权限
     */
    @Operation(summary = "获取当前用户角色下的数据权限")
    @GetMapping("/getDataPermission")
    public R<DeptDataPermissionEntity> getDataPermission() {
        AuthUser user = SecurityUtils.getUser();
        return R.success(sysRoleService.getDataPermission(user));
    }

    /**
     * 导出excel 表格
     *
     * @return
     */
    @ResponseExcel
    @GetMapping(RestApiConfig.EXPORT_EXCEL)
    @PreAuthorize("@pms.hasPermission('sys_role_export')")
    public List<RoleExcelVO> exportExcel() {
        return sysRoleService.listRole();
    }

    /**
     * 导入角色
     *
     * @param excelVOList   角色列表
     * @param bindingResult 错误信息列表
     * @return ok fail
     */
    @PostMapping(RestApiConfig.IMPORT_EXCEL)
    @PreAuthorize("@pms.hasPermission('sys_role_import')")
    public R<?> importExcel(@RequestExcel List<RoleExcelVO> excelVOList, BindingResult bindingResult) {
        return sysRoleService.importRole(excelVOList, bindingResult);
    }

}
